#include <arpa/inet.h>
#include <errno.h>
#include <sys/sockcall.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>

//int16_t endian
#define endian_byte_swap16(a) \
    (((uint16_t)(a)&0xff00) >> 8) | (((uint16_t)(a)&0xff) << 8)

//int64_t endian
#define endian_byte_swap32(a) \
       ((((uint32_t)(a) & 0xff000000) >> 24) | \
    (((uint32_t)(a) & 0x00ff0000) >> 8) | \
    (((uint32_t)(a) & 0x0000ff00) << 8) | \
    (((uint32_t)(a) & 0x000000ff) << 24)) 

//return: big endian 1  little endian 0
static int check_cpu_endian()
{
    union
    {
        uint32_t i;
        uint8_t s[4];
    } c;

    c.i = 0x12345678;
    return (c.s[0] == 0x12);
}

//network always use big endian order

//host bytes order to net bytes order
uint32_t htonl(uint32_t h)
{
    return check_cpu_endian() ? h : endian_byte_swap32(h);
}

uint32_t nltoh(uint32_t n)
{
    return check_cpu_endian() ? n : endian_byte_swap32(n);
}

uint16_t htons(uint16_t h)
{
    return check_cpu_endian(h) ? h : endian_byte_swap16(h);
}

uint16_t ntohs(uint16_t n)
{
    return check_cpu_endian(n) ? n : endian_byte_swap16(n);
}

int inet_pton(int family, const char *strptr, void *addrptr)
{
    if (family == AF_INET)
    {
        struct in_addr in_val;
        if (inet_aton(strptr, &in_val))
        {
            memcpy(addrptr, &in_val, sizeof(struct in_addr));
            return 1;
        }
        else   
        {
            return 0;
        }
    }
    errno=EAFNOSUPPORT;
    return -1;
}

const char *inet_ntop(int family,const void *addrptr,char *strptr,size_t len)
{
    const char *p=addrptr;
    if(family==AF_INET)
    {
        char temp[INET_ADDRSTRLEN];
        snprintf(temp,sizeof(temp),"%d.%d.%d.%d",p[0],p[1],p[2],p[3]);
        if(strlen(temp)>=len)
        {
            errno=ENOSPC;
            return NULL;
        }
        strcpy(strptr,temp);
        return strptr;
    }
    return NULL;
}